﻿// <copyright file="Utility.cs" company="TenneySoftware">
// Copyright (c) 2009 All Right Reserved
// </copyright>
// <author>Robert Tenney</author>
// <email>rob10e@yahoo.com</email>
// <date>April 2009</date>
// <summary>Utility class provides useful methods for use with the RPGEngine and it's modules.</summary>

// License:

// Product: RPGRoguelikeEngine .Net
// Author: Robert N. Tenney
// Copyright: April 2009

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation version 2
// of the License.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

// This license covers all source code, binaries, and other materials related to this project
// unless specifically stated otherwise.

using System;
using System.Drawing;

namespace TenneySoftware.Engine {
    /// <summary>
    /// Utility class provides useful methods for use with the RPGEngine and it's modules.
    /// </summary>
    public static class Utility {
        /// <summary>
        /// A static random number generator.
        /// </summary>
        private static Random rand = new Random();

        /// <summary>
        /// A static method to normalize a number. The number will be adjusted to have the same
        /// weight as before, but will fall between the lower and upper values.
        /// </summary>
        /// <param name="lower">The lower end of the range.</param>
        /// <param name="upper">The upper end of the range.</param>
        /// <param name="number">The number to normalize.</param>
        /// <returns>The normalized number.</returns>
        public static int Normalize(int lower, int upper, int number) {
            int result = 0;
            double factor = (100.0 / (double)upper) - (double)lower;
            int normal = (int)(number * factor);
            result = normal + lower;
            return result;
        }

        /// <summary>
        /// A static method that uses the default random number generator to return a 50/50
        /// percent chance of the result being true or false.
        /// </summary>
        /// <returns>True or false.</returns>
        public static bool FlipCoin() {
            return FlipCoin(rand);
        }

        /// <summary>
        /// A static method that uses the given random number generator to return a 50/50
        /// percent chance of the result being true or false.
        /// </summary>
        /// <param name="rand">Random number object to use.</param>
        /// <returns>True or false.</returns>
        public static bool FlipCoin(Random rand) {
            if (rand.Next(2) == 0) {
                return true;
            } else {
                return false;
            }
        }

        /// <summary>
        /// Method to determine the distance between two points.
        /// </summary>
        /// <param name="pt1">First point.</param>
        /// <param name="pt2">Second point.</param>
        /// <returns>Distance between the points as a double.</returns>
        public static double Distance(Point pt1, Point pt2) {
            double result = 0;
            result = Math.Sqrt(Math.Pow(Math.Abs((double)(pt1.X - pt2.X)), 2) + Math.Pow(Math.Abs((double)(pt1.Y - pt2.Y)), 2));
            return result;
        }

        /// <summary>
        /// A static method that will return a point that is forward of the given point facing
        /// the given direction.
        /// </summary>
        /// <param name="location">Reference location.</param>
        /// <param name="direction">Direction that location is facing.</param>
        /// <returns>A point that is forward from the reference location.</returns>
        public static Point PointForward(Point location, Direction direction) {
            Point result = new Point();
            switch (direction) {
                case Direction.North:
                    result.X = 0;
                    result.Y = -1;
                    break;
                case Direction.South:
                    result.X = 0;
                    result.Y = 1;
                    break;
                case Direction.East:
                    result.X = 1;
                    result.Y = 0;
                    break;
                case Direction.West:
                    result.X = -1;
                    result.Y = 0;
                    break;
                case Direction.Northeast:
                    result.X = 1;
                    result.Y = -1;
                    break;
                case Direction.Northwest:
                    result.X = -1;
                    result.Y = -1;
                    break;
                case Direction.Southeast:
                    result.X = 1;
                    result.Y = 1;
                    break;
                case Direction.Southwest:
                    result.X = -1;
                    result.Y = 1;
                    break;
            }
            
            result.Offset(location);
            return result;
        }

        /// <summary>
        /// A static method that returns the opposing direction of the given direction.
        /// </summary>
        /// <param name="direction">Direction to find the opposing direction.</param>
        /// <returns>The opposing direction of the given direction.</returns>
        public static Direction OppositeDirection(Direction direction) {
            Direction result = Direction.Void;
            switch (direction) {
                case Direction.North:
                    result = Direction.South;
                    break;
                case Direction.South:
                    result = Direction.North;
                    break;
                case Direction.East:
                    result = Direction.West;
                    break;
                case Direction.West:
                    result = Direction.East;
                    break;
            }
            
            return result;
        }
    }
}